package oplog

import (
	"bytes"
	"io/ioutil"
	"time"

	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/ddd/ginhook"

	"github.com/gin-gonic/gin"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/core/oplogd"
)

const (
	opLogKey = "__oplog__"
)

// OplogRoute 日志路由
func OplogRoute(action, desc string, handler gin.HandlerFunc) gin.HandlerFunc {
	return func(c *gin.Context) {
		WrapAction(c, action, desc)
		handler(c)

	}
}

// Oplog 操作日志中间件
func Oplog(d oplogd.OpLogDomain) gin.HandlerFunc {
	return func(c *gin.Context) {

		req := c.Request
		ol := &oplogd.OpLogEntity{
			OpTime: time.Now(),
			Action: req.URL.Path,
			URL:    req.URL.String(),
			Head:   req.Header,
			IP:     c.ClientIP(),
			Agent:  req.UserAgent(),
		}
		if req.Body == nil {
			return
		}
		//safe := &io.LimitedReader{R: req.Body, N: 4096}
		requestbody, _ := ioutil.ReadAll(req.Body)
		req.Body.Close()
		bf := bytes.NewBuffer(requestbody)
		c.Request.Body = ioutil.NopCloser(bf)
		n := 4096
		if n > len(requestbody) {
			n = len(requestbody)
		}
		ol.Input = string(requestbody[0:n])
		c.Set("Body", requestbody)
		c.Set(opLogKey, ol)
		c.Next()
		ol.UseTime = int64(time.Since(ol.OpTime) / time.Millisecond)

		ctx := ginhook.FromContext(c)
		if ctx != nil {
			_ = d.OpLogAggregateRoot().AddOpLog(ctx, ol)
		}
		c.HandlerName()
	}
}

// FromCtx 获取操作记录
func FromCtx(c *gin.Context) *oplogd.OpLogEntity {
	if ol, ok := c.Get(opLogKey); ok {
		return ol.(*oplogd.OpLogEntity)
	}
	return nil
}

// WrapAction 赋值行为
func WrapAction(c *gin.Context, action, desc string) {
	if ol := FromCtx(c); ol != nil {
		ol.Action = action
		ol.Desc = desc
	}
}

// WrapModule 赋值uid
func WrapModule(c *gin.Context, module string) {
	if ol := FromCtx(c); ol != nil {
		ol.Module = module
	}
}

// WrapUID 赋值uid
func WrapUID(c *gin.Context, uid string) {
	if ol := FromCtx(c); ol != nil {
		ol.UID = uid
	}
}

// WrapModules 包装模块及用户uid信息
func WrapModules(c *gin.Context, handler func(*oplogd.OpLogEntity)) {
	if handler == nil {
		return
	}
	if ol := FromCtx(c); ol != nil {
		handler(ol)
	}
}
